package util

import (
	"bytes"
	"common/logging"
	"common/werror"
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

type THttpResponseData struct {
	Code  int         `json:"errorCode"`
	Msg   string      `json:"msg"`
	MsgID string      `json:"msgid"`
	Data  interface{} `json:"data"`
}

type TLogRequestInfo struct {
	Method       string
	URL          string
	User_id      string
	X_Auth_Token string
	Form         interface{}
	Body         interface{}
}

func GetErrorMsg(code int) (bool, string) {
	msg, ok := ErrMap[code]
	return ok, msg
}

func ResponseSerialize(req *http.Request, tick time.Time, msgid string, err *werror.WError, repayload interface{}) []byte {
	// log print
	body := ""
	b_body, ee := ioutil.ReadAll(req.Body)
	if ee == nil {
		body = string(b_body)
	}

	logReq := TLogRequestInfo{
		Method: req.Method,
		URL:    req.RequestURI,
		Form:   req.Form,
		Body:   body,
	}

	var arraybytes []byte
	if err != nil {
		response := &THttpResponseData{}
		response.Code = err.Code()
		response.Msg = string(err.ToString())
		response.MsgID = msgid
		response.Data = map[string]interface{}{}
		ret, ee := json.Marshal(response)
		if ee != nil {
			logging.Error("[ResponseSerialize] Failed, %s, data = %v", string(err.ToString()), response)
			panic("[ResponseSerialize] Failed, " + ee.Error())
		}
		arraybytes = ret
	} else {
		response := &THttpResponseData{}
		response.Code = ERR_CODE_SUCCESS
		response.Msg = ERR_STR_SUCCESS
		response.MsgID = msgid
		response.Data = repayload
		ret, ee := json.Marshal(response)
		if ee != nil {
			logging.Error("[ResponseSerialize] Failed, %s, data = %v", string(err.ToString()), repayload)
			panic("[ResponseSerialize] Failed, " + ee.Error())
		}
		arraybytes = ret
	}

	stamp := time.Now().Sub(tick)
	logging.Info("HANDLE_LOG: url = %s, time = %v, request = %+v, response = %s", req.RequestURI, stamp, logReq, string(arraybytes))
	return arraybytes
}

func ResponseSerializeEx(req *http.Request, tick time.Time, msgid string, err *werror.WError, repayload interface{}) []byte {
	// log print
	body := ""
	b_body, ee := ioutil.ReadAll(req.Body)
	if ee == nil {
		body = string(b_body)
	}

	logReq := TLogRequestInfo{
		Method: req.Method,
		URL:    req.RequestURI,
		Form:   req.Form,
		Body:   body,
	}

	var arraybytes []byte
	if err != nil {
		response := &THttpResponseData{}
		response.Code = err.Code()
		response.Msg = string(err.ToString())
		response.MsgID = msgid
		response.Data = map[string]interface{}{}
		ret, ee := json.Marshal(response)
		if ee != nil {
			logging.Error("[ResponseSerialize] Failed, %s, data = %v", string(err.ToString()), response)
			panic("[ResponseSerialize] Failed, " + ee.Error())
		}
		arraybytes = ret
	} else {
		ret, ee := json.Marshal(repayload)
		if ee != nil {
			logging.Error("[ResponseSerialize] Failed, %s, data = %v", string(err.ToString()), repayload)
			panic("[ResponseSerialize] Failed, " + ee.Error())
		}
		arraybytes = ret
	}

	stamp := time.Now().Sub(tick)
	logging.Info("HANDLE_LOG: url = %s, time = %v, request = %+v, response = %s", req.RequestURI, stamp, logReq, string(arraybytes))
	return arraybytes
}

func GetRequestBody(req *http.Request, v interface{}) (interface{}, *werror.WError) {
	buff := bytes.NewBufferString("")
	_, err := io.Copy(buff, req.Body)
	if err != nil {
		logging.Error("[GetRequestBody] copy req body error, request=%v, error=%s", req.Body, err.Error())
		return nil, werror.NewError(1003, err.Error())
	}
	text := buff.String()
	req.Body = ioutil.NopCloser(strings.NewReader(text))

	err = json.Unmarshal([]byte(text), v)
	if err != nil {
		logging.Error("[GetRequestBody] decode json body error, text=%s, error=%s", text, err.Error())
		return nil, werror.NewError(1003, err.Error())
	}

	return v, nil
}
